﻿using Kylin.Wiki.Core.Configuration;
using Kylin.Wiki.Core.Extensions;
using Kylin.Wiki.Core.Utilities;
using Kylin.Wiki.Model.Api;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Threading.Tasks;

namespace Kylin.Wiki.Web.Common.Filter
{
    public class ApiAuthorizeFilter : Attribute, IAuthorizationFilter
    {
        public ApiAuthorizeFilter()
        {

        }
        /// <summary>
        /// Token验证
        /// </summary>
        /// <param name="context"></param>
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            //无需验证
            if (context.ActionDescriptor.EndpointMetadata.Any(item => item is AllowAnonymousAttribute))
            {
                return;
            }


            DateTime expDate = context.HttpContext.User.Claims.Where(x => x.Type == JwtRegisteredClaimNames.Exp)
                .Select(x => x.Value).FirstOrDefault().GetTimeSpmpToDate();
            //如果过期时间小于设置定分钟数的1/3时，返回状态需要刷新token
            if (expDate < DateTime.Now || (expDate - DateTime.Now).TotalMinutes < AppSetting.Secret.ExpMinutes / 3)
            {
                context.Result = new JsonResult(new { Success = false, Code = HttpStatusCode.Unauthorized, Message = "Token即将过期,请更换token" }); 
                return;
            }
            if (!IsVaild(context))
            {
                context.Result = new JsonResult(new { Success = false, Code = HttpStatusCode.Unauthorized, Message = "验证失败" }); 
                return;
            }
        }

        /// <summary>
        /// 判断验证
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        public bool IsVaild(AuthorizationFilterContext context)
        {
            string fixedoken = "";
            //如果token已失效，直接获取header里的token
            if (!context.HttpContext.User.Identity.IsAuthenticated)
            {
                fixedoken = context.HttpContext.Request.Headers[AppSetting.TokenHeaderName];
                fixedoken = fixedoken?.Replace("Bearer ", "");
                //判断是否传入了token
                if (string.IsNullOrEmpty(fixedoken))
                {
                    return false;
                }
                //解析token
                int userId = JwtHelper.GetUserId(fixedoken);
                if (userId <= 0)
                {
                    return false;
                }
                context.AddIdentity(userId);
            }
            else
            {
                fixedoken = ((ClaimsIdentity)context.HttpContext.User.Identity)
                ?.BootstrapContext?.ToString();
            }
            if (string.IsNullOrEmpty(fixedoken))
            {
                return false;
            } 
            return true;
        }

    }
}
